package com.karrim.server.io.file;

import com.karrim.server.util.def.Event;
import com.karrim.server.util.def.TargetedEvent;
import java.io.File;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

/**
 *
 * @author andrea
 */
public class FileMonitor {

    public class FileMonitorTask extends TimerTask {

        FileMonitorTask(FileListener listener) {
            this.listener = listener;
            target = listener.getTarget();
            exist = target.exists();
            lastModified = target.lastModified();
        }

        @Override
        public void run() {
            if (exist) {
                created = false;
                deleted = (exist = target.exists()) ? false : true;
            } else {
                deleted = false;
                created = (exist = target.exists()) ? true : false;
            }
            modified = lastModified != target.lastModified();
            FileEvent event = new FileEventImpl(this);
            if (created) {
                listener.onCreation(event);
            } else if (deleted) {
                listener.onDeletion(event);
            }
            if (modified) {
                listener.onLastModifiedChange(event);
            }
            lastModified = target.lastModified();
        }
        private boolean created = false;
        private boolean exist;
        private boolean deleted = false;
        private long lastModified;
        private FileListener listener;
        private boolean modified = false;
        private File target;
    }

    public interface FileEvent extends Event<File> {

        public long getLastLength();

        public long getLastModified();

        public boolean isCreated();

        public boolean isDeleted();

        public boolean isModified();
    }

    public class FileEventImpl implements FileEvent {

        private FileEventImpl(FileMonitorTask task) {
            this.task = task;
            lastModified = task.lastModified;
            created = task.created;
            deleted = task.deleted;
        }

        @Override
        public long getLastLength() {
            return lastModified;
        }

        @Override
        public long getLastModified() {
            return lastModified;
        }

        @Override
        public boolean isCreated() {
            return created;
        }

        @Override
        public boolean isDeleted() {
            return deleted;
        }

        @Override
        public boolean isModified() {
            return modified;
        }

        @Override
        public File getSource() {
            return task.target;
        }
        private boolean created = false;
        private boolean exist;
        private boolean deleted = false;
        private long lastModified;
        private boolean modified = false;
        private FileMonitorTask task;
    }

    private FileMonitor() {
    }

    public void addFileListener(FileListener listener) {
        Timer timer = new Timer("FileMonitorTask@" + listener.getTarget().getAbsolutePath());
        timer.schedule(new FileMonitorTask(listener), 0, INTERVAL);
        timers.put(listener.getTarget().getAbsolutePath(), timer);
    }

    public static FileMonitor get() {
        return monitor;
    }

    public void removeFileListener(FileListener listener) {
        Timer timer = timers.remove(listener.getTarget().getAbsolutePath());
        timer.cancel();
    }
    private static FileMonitor monitor = new FileMonitor();
    private HashMap<String, Timer> timers = new HashMap<>();
    public final long INTERVAL = 2000;
}
